package com.bf.electroplating.service.impl;

import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bf.electroplating.login.UserContext;
import com.bf.electroplating.login.UserDetail;
import com.bf.electroplating.mapper.InspectionTaskMapper;
import com.bf.electroplating.pojo.dto.inspection.InspectionTaskDTO;
import com.bf.electroplating.pojo.entity.*;
import com.bf.electroplating.pojo.enums.*;
import com.bf.electroplating.pojo.vo.inspection.InspectionTaskVO;
import com.bf.electroplating.pojo.vo.sysuser.UserListVO;
import com.bf.electroplating.service.*;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 15451
 * @description 针对表【inspection_task(巡检任务表)】的数据库操作Service实现
 * @createDate 2025-06-16 09:09:25
 */
@Service
public class InspectionTaskServiceImpl extends ServiceImpl<InspectionTaskMapper, InspectionTask>
        implements InspectionTaskService {

    @Resource
    private InspectionTaskCompanyService inspectionTaskCompanyService;
    @Resource
    private InspectionTaskFacilityService inspectionTaskFacilityService;
    @Resource
    private InspectionTaskUserService inspectionTaskUserService;
    @Resource
    private ComEnvironmentallyFacilityService comEnvironmentallyFacilityService;
    @Resource
    private InspectionFeedbackService inspectionFeedbackService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private ComCompanyService comCompanyService;

    @Override
    public List<UserListVO> getInspectors() {
        return sysUserService.getUserListVOByRoleCode(RoleCodeEnum.HBGJ.getCode());
    }

    @Override
    public Page<InspectionTaskVO> getTaskList(InspectionTaskDTO dto) {
        Page<InspectionTask> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<InspectionTask> wrapper = new LambdaQueryWrapper<>();

        if (StringUtils.hasText(dto.getInspectionType())) {
            wrapper.eq(InspectionTask::getInspectionType, dto.getInspectionType());
        }
        if (StringUtils.hasText(dto.getStatus())) {
            wrapper.eq(InspectionTask::getStatus, dto.getStatus());
        }
        if (StringUtils.hasText(dto.getInspectionName())) {
            wrapper.like(InspectionTask::getInspectionName, dto.getInspectionName());
        }

        Page<InspectionTask> taskPage = this.page(page, wrapper);
        Page<InspectionTaskVO> voPage = new Page<>();
        BeanUtils.copyProperties(taskPage, voPage, "records");

        List<InspectionTaskVO> voList = taskPage.getRecords().stream().map(task -> {
            InspectionTaskVO vo = new InspectionTaskVO();
            BeanUtils.copyProperties(task, vo);
            vo.setStatusString(InspectionTaskStatusEnum.getDesc(vo.getStatus()));
            vo.setInspectionType(InspectionTypeEnum.getDesc(vo.getInspectionType()));
            vo.setInspectionFrequency(InspectionFrequencyEnum.getDesc(vo.getInspectionFrequency()));
            vo.setInspectionDeadlineList(getDateStr(task.getStartTime()) + " ~ " + getDateStr(task.getEndTime()));
            if (InspectionTypeEnum.COMPANY.getCode().equals(task.getInspectionType())) {
                List<InspectionTaskCompany> taskCompanies = inspectionTaskCompanyService.list(new LambdaQueryWrapper<InspectionTaskCompany>().eq(InspectionTaskCompany::getTaskId, task.getId()));
                List<ComCompany> comCompanies = comCompanyService.listByIds(taskCompanies.stream().map(InspectionTaskCompany::getCompanyId).toList());
                String collect = comCompanies.stream().map(ComCompany::getCompanyName).collect(Collectors.joining("、"));
                vo.setInspectionPointList(collect);
            } else {
                List<InspectionTaskFacility> taskFacilities = inspectionTaskFacilityService.list(new LambdaQueryWrapper<InspectionTaskFacility>().eq(InspectionTaskFacility::getTaskId, task.getId()));
                List<ComEnvironmentallyFacility> comEnvironmentallyFacilities = comEnvironmentallyFacilityService.listByIds(taskFacilities.stream().map(InspectionTaskFacility::getFacilityId).toList());
                String collect = comEnvironmentallyFacilities.stream().map(ComEnvironmentallyFacility::getEnvironmentalFacilityName).collect(Collectors.joining("、"));
                vo.setInspectionPointList(collect);
            }
            List<String> list = inspectionTaskUserService.list(new LambdaQueryWrapper<InspectionTaskUser>().eq(InspectionTaskUser::getTaskId, task.getId())).stream().map(InspectionTaskUser::getUserId).toList();
            List<SysUser> users = sysUserService.listByIds(list);
            vo.setInspectionPersonnelList(users.stream().map(SysUser::getUserName).collect(Collectors.joining("、")));
            return vo;
        }).collect(Collectors.toList());

        voPage.setRecords(voList);
        return voPage;
    }

    private String getDateStr(Date date) {
        LocalDate localDate = date.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return formatter.format(localDate);
    }

    @Override
    public InspectionTaskVO getTaskById(String id) {
        InspectionTask task = this.getById(id);
        if (task == null) {
            return null;
        }
        InspectionTaskVO vo = new InspectionTaskVO();
        BeanUtils.copyProperties(task, vo);
        List<String> dateList=new ArrayList<>();
        dateList.add(getDateStr(task.getStartTime()));
        dateList.add(getDateStr(task.getEndTime()));
        vo.setInspectionDeadline(dateList);
        if (InspectionTypeEnum.COMPANY.getCode().equals(vo.getInspectionType())) {
            List<InspectionTaskCompany> taskCompanies = inspectionTaskCompanyService.list(new LambdaQueryWrapper<InspectionTaskCompany>().eq(InspectionTaskCompany::getTaskId, id));
            vo.setInspectionPoint(taskCompanies.stream().map(InspectionTaskCompany::getCompanyId).toList());
        } else {
            List<InspectionTaskFacility> taskFacilities = inspectionTaskFacilityService.list(new LambdaQueryWrapper<InspectionTaskFacility>().eq(InspectionTaskFacility::getTaskId, id));
            vo.setInspectionPoint(taskFacilities.stream().map(InspectionTaskFacility::getFacilityId).toList());
        }
        vo.setInspectionPersonnel(inspectionTaskUserService.list(new LambdaQueryWrapper<InspectionTaskUser>().eq(InspectionTaskUser::getTaskId, id)).stream().map(InspectionTaskUser::getUserId).toList());
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveTask(InspectionTaskVO vo) {
        InspectionTask task = new InspectionTask();
        BeanUtils.copyProperties(vo, task);
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            task.setStartTime(sdf.parse(vo.getInspectionDeadline().get(0)));
            task.setEndTime(sdf.parse(vo.getInspectionDeadline().get(1)));
        } catch (ParseException e) {
            log.error("日期解析失败：" + e.getMessage());
        }
        if (task.getStartTime().before(new Date())) {
            task.setStatus(InspectionTaskStatusEnum.AWAIT.getCode());
        }else {
            task.setStatus(InspectionTaskStatusEnum.NO_START.getCode());
        }
        boolean save = this.save(task);
        if (InspectionTypeEnum.COMPANY.getCode().equals(vo.getInspectionType())) {
            List<InspectionTaskCompany> collect = vo.getInspectionPoint().stream().map(point -> {
                InspectionTaskCompany company = new InspectionTaskCompany();
                company.setTaskId(task.getId());
                company.setCompanyId(point);
                return company;
            }).toList();
            inspectionTaskCompanyService.saveBatch(collect);
        } else {
            List<InspectionTaskFacility> collect = vo.getInspectionPoint().stream().map(point -> {
                InspectionTaskFacility facility = new InspectionTaskFacility();
                facility.setTaskId(task.getId());
                facility.setFacilityId(point);
                return facility;
            }).toList();
            inspectionTaskFacilityService.saveBatch(collect);
        }
        saveUser(vo, task);
        vo.getInspectionPoint().forEach(id -> saveFeedback(id, task));
        return save;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateTask(InspectionTaskVO vo) {
        InspectionTask task = new InspectionTask();
        BeanUtils.copyProperties(vo, task);
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            task.setStartTime(sdf.parse(vo.getInspectionDeadline().get(0)));
            task.setEndTime(sdf.parse(vo.getInspectionDeadline().get(1)));
        } catch (ParseException e) {
            log.error("日期解析失败：" + e.getMessage());
        }
        InspectionTask byId = getById(task.getId());
        if (!byId.getInspectionType().equals(vo.getInspectionType())){
            inspectionFeedbackService.remove(new LambdaQueryWrapper<InspectionFeedback>().eq(InspectionFeedback::getTaskId, byId.getId()));
        }
        if (InspectionTypeEnum.COMPANY.getCode().equals(vo.getInspectionType())) {
            List<InspectionTaskCompany> taskCompanies = inspectionTaskCompanyService.list(new LambdaQueryWrapper<InspectionTaskCompany>().eq(InspectionTaskCompany::getTaskId, task.getId()));
            vo.getInspectionPoint().stream().filter(point -> taskCompanies.stream().noneMatch(company -> company.getCompanyId().equals(point))).forEach(point -> {
                InspectionTaskCompany company = new InspectionTaskCompany();
                company.setTaskId(task.getId());
                company.setCompanyId(point);
                inspectionTaskCompanyService.save(company);
                saveFeedback(point, task);
            });
            taskCompanies.stream().filter(company -> vo.getInspectionPoint().stream().noneMatch(point -> point.equals(company.getCompanyId()))).forEach(company -> {
                inspectionTaskCompanyService.removeById(company.getId());
                inspectionFeedbackService.remove(new LambdaQueryWrapper<InspectionFeedback>().eq(InspectionFeedback::getTaskId, company.getTaskId()).eq(InspectionFeedback::getInspectionPoint, company.getCompanyId()));
            });
            inspectionTaskFacilityService.remove(new LambdaQueryWrapper<InspectionTaskFacility>().eq(InspectionTaskFacility::getTaskId, task.getId()));
        } else {
            List<InspectionTaskFacility> taskFacilities = inspectionTaskFacilityService.list(new LambdaQueryWrapper<InspectionTaskFacility>().eq(InspectionTaskFacility::getTaskId, task.getId()));
            vo.getInspectionPoint().stream().filter(point -> taskFacilities.stream().noneMatch(facility -> facility.getFacilityId().equals(point))).forEach(point -> {
                InspectionTaskFacility facility = new InspectionTaskFacility();
                facility.setTaskId(task.getId());
                facility.setFacilityId(point);
                inspectionTaskFacilityService.save(facility);
                saveFeedback(point, task);
            });
            taskFacilities.stream().filter(facility -> vo.getInspectionPoint().stream().noneMatch(point -> point.equals(facility.getFacilityId()))).forEach(facility -> {
                inspectionTaskFacilityService.removeById(facility.getId());
                inspectionFeedbackService.remove(new LambdaQueryWrapper<InspectionFeedback>().eq(InspectionFeedback::getTaskId, facility.getTaskId()).eq(InspectionFeedback::getInspectionPoint, facility.getFacilityId()));
            });
            inspectionTaskCompanyService.remove(new LambdaQueryWrapper<InspectionTaskCompany>().eq(InspectionTaskCompany::getTaskId, task.getId()));
        }
        inspectionTaskUserService.remove(new LambdaQueryWrapper<InspectionTaskUser>().eq(InspectionTaskUser::getTaskId, task.getId()));
        saveUser(vo, task);
        return this.updateById(task);
    }

    private void saveFeedback(String point, InspectionTask task) {
        InspectionFeedback feedback = new InspectionFeedback();
        feedback.setInspectionPoint(point);
        feedback.setTaskId(task.getId());
        feedback.setInspectionType(task.getInspectionType());
//        feedback.setInspectionStatus(InspectionStatusEnum.AWAIT.getCode());
        inspectionFeedbackService.save(feedback);
    }

    private void saveUser(InspectionTaskVO vo, InspectionTask task) {
        List<InspectionTaskUser> taskUsers = vo.getInspectionPersonnel().stream().map(point -> {
            InspectionTaskUser user = new InspectionTaskUser();
            user.setTaskId(task.getId());
            user.setUserId(point);
            return user;
        }).toList();
        inspectionTaskUserService.saveBatch(taskUsers);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTask(String id) {
        inspectionTaskUserService.remove(new LambdaQueryWrapper<InspectionTaskUser>().eq(InspectionTaskUser::getTaskId, id));
        inspectionFeedbackService.remove(new LambdaQueryWrapper<InspectionFeedback>().eq(InspectionFeedback::getTaskId, id));
        inspectionTaskCompanyService.remove(new LambdaQueryWrapper<InspectionTaskCompany>().eq(InspectionTaskCompany::getTaskId, id));
        inspectionTaskFacilityService.remove(new LambdaQueryWrapper<InspectionTaskFacility>().eq(InspectionTaskFacility::getTaskId, id));
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeleteTask(List<String> ids) {
        inspectionTaskUserService.remove(new LambdaQueryWrapper<InspectionTaskUser>().in(InspectionTaskUser::getTaskId, ids));
        inspectionFeedbackService.remove(new LambdaQueryWrapper<InspectionFeedback>().in(InspectionFeedback::getTaskId, ids));
        inspectionTaskCompanyService.remove(new LambdaQueryWrapper<InspectionTaskCompany>().in(InspectionTaskCompany::getTaskId, ids));
        inspectionTaskFacilityService.remove(new LambdaQueryWrapper<InspectionTaskFacility>().in(InspectionTaskFacility::getTaskId, ids));
        return this.removeByIds(ids);
    }
}




